/***************************************************************************
 *   Copyright (C) 2011 by The rPem3d developers                           *
 *   elseifkk@users.sf.net                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "config.h"
#include "okruncls.h"
#include "pix.h"

#include <qpushbutton.h>
#include <qstring.h>
#include <qtextstream.h>
#include <qlistview.h>
#include <qtable.h>
#include <qtextedit.h>
#include <qtextcodec.h>
#include <qmemarray.h>
#include <qlabel.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qtimer.h>
#include <qgroupbox.h>
#include <qspinbox.h>

#include <kfiledialog.h>
#include <kcombobox.h>
#include <kmessagebox.h>

void okRunCls::closeEvent(QCloseEvent *e) {
    saveConfig(HOME+CONFIG);
    e->accept();
}

okRunCls::okRunCls(QWidget *parent, const char *name)
:okRunDlg(parent, name) {
    QString cap="okRun";
    QString version="";
    #ifdef VERSION
    version=VERSION;
    #else
    version="unknown";
    #endif
    setCaption(cap+" version "+version);
    QPalette pal = comListBox->palette();
    pal.setColor ( QColorGroup::Highlight, qRgb ( 205,234,255 ) );
//     pal.setColor ( QColorGroup::HighlightedText, qRgb ( 255,0,255 ) );
    pal.setColor ( QColorGroup::HighlightedText, qRgb ( 0,71,171 ) );
    setPalette(pal);
    currentRowHeight=0;

    sp= new QProcess(this);
    connect ( sp, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdouts() ) );
    connect ( sp, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderrs() ) );
    connect ( sp, SIGNAL ( processExited() ), this,  SLOT ( sendDone() ) );

    sp1= new QProcess(this);
    connect ( sp1, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdout1() ) );
    connect ( sp1, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderr1() ) );
    connect ( sp1, SIGNAL ( processExited() ), this,  SLOT ( sendDone1() ) );

    pp = new QProcess(this);
    connect ( pp, SIGNAL ( readyReadStdout() ), this,  SLOT ( slotReadStdoutp() ) );
    connect ( pp, SIGNAL ( readyReadStderr() ), this,  SLOT ( slotReadStderrp() ) );
    connect ( pp, SIGNAL ( processExited() ), this,  SLOT ( sendDonep() ) );

    okpic = new QPixmap(button_ok);
    ngpic = new QPixmap(button_cancel);
    fkpic = new QPixmap(rightarrow);
    erpic = new QPixmap(button_error);

    comListBox->setColumnStretchable(0,false);
    comListBox->setColumnStretchable(1,false);
    comListBox->setColumnStretchable(2,true);

    comListBox->setColumnReadOnly(0,true);
    maxcomlen=0;
    numcom=0;
    printLbls();
    loopt = new QTimer(this);
    connect( loopt, SIGNAL(timeout()), this, SLOT(sendACommand()) );

    HOME=getenv("HOME");
    if ((!HOME.isEmpty())&&(!HOME.endsWith("/"))) HOME.append("/");
    loadConfig(HOME+CONFIG);
}

void okRunCls::loadConfig(QString f) {
    KConfig *conf = new KConfig ( f );
    if ( conf==NULL ) return;

    KConfigGroup histGroup ( conf,"History" );
    KConfigGroup externalGroup ( conf,"Externals" );
    KConfigGroup scriptGroup ( conf,"Scripts" );

    SCRPATH = scriptGroup.readEntry("Script path",SCRPATH_DEF);
    if ((!SCRPATH.isEmpty())&&(!SCRPATH.endsWith("/"))) SCRPATH.append("/");
    SENDC=scriptGroup.readEntry("sendc",SENDC_DEF);

    PING=externalGroup.readEntry("ping",PING_DEF);


    ipBox->setHistoryItems(histGroup.readListEntry("Remote host history"));
    ipBox->completionObject()->setItems(histGroup.readListEntry("Remote host completion"));

    portBox->setHistoryItems(histGroup.readListEntry("Port history"));
    portBox->completionObject()->setItems(histGroup.readListEntry("Port completion"));

    finBox->setHistoryItems(histGroup.readListEntry("Command file history"));
    finBox->completionObject()->setItems(histGroup.readListEntry("Command file completion"));

    comBox->setHistoryItems(histGroup.readListEntry("Command history"));
    comBox->completionObject()->setItems(histGroup.readListEntry("Command completion"));
    delete conf;
}

void okRunCls::saveConfig(QString f) {
    KConfig *conf = new KConfig(f);
    if (conf==NULL) return;
    KConfigGroup histGroup ( conf,"History" );
    KConfigGroup externalGroup ( conf,"Externals" );
    KConfigGroup scriptGroup ( conf,"Scripts" );

    scriptGroup.writeEntry("Script path",SCRPATH);
    scriptGroup.writeEntry("sendc",SENDC);
    externalGroup.writeEntry("ping",PING);

    histGroup.writeEntry("Remote host history",ipBox->historyItems());
    histGroup.writeEntry("Remote host completion",ipBox->completionObject()->items());

    histGroup.writeEntry("Port history",portBox->historyItems());
    histGroup.writeEntry("Port completion",portBox->completionObject()->items());

    histGroup.writeEntry("Command file history",finBox->historyItems());
    histGroup.writeEntry("Command file completion",finBox->completionObject()->items());

    histGroup.writeEntry("Command history",comBox->historyItems());
    histGroup.writeEntry("Command completion",comBox->completionObject()->items());

    histGroup.sync();
    externalGroup.sync();
    scriptGroup.sync();

    delete conf;
}

void okRunCls::openFileSlot() {
    QString fin=KFileDialog::getOpenFileName ( "","*.*|All (*.*)",this, "Select Command File" );
    if (fin.isEmpty()) return;
    finBox->insertItem(fin);
    finBox->setCurrentItem(fin);
    readSlot();
}

void okRunCls::procLine(QString linein, int ir, bool full) {
    QString line;
    if ((!comListBox->text(ir,2).isEmpty())&&full) {
        line=linein+" "+comListBox->text(ir,2);
    } else {
        line=linein;
    }
    line=line.stripWhiteSpace().simplifyWhiteSpace();
    if (!line.isEmpty()) {
        comListBox->blockSignals(true);
        if (line.startsWith("#")) {
            comListBox->setText(ir,1,line);
            comListBox->clearCell(ir,0);
        } else {
            QString command=line.section(" ",0,0);
            QString comment=line.section(" ",1);
            comListBox->clearCell(ir,0);
            comListBox->setText(ir,0,"ready");
            comListBox->setText(ir,1,command);
            numcom++;
            printLbls();
            if (command.length()>maxcomlen) maxcomlen=command.length();
            if (!comment.isEmpty()) comListBox->setText(ir,2,comment);
        }
        comListBox->blockSignals(false);
    }
}

void okRunCls::readSlot() {

    if (finBox->currentText().isEmpty()) return;

    finBox->addToHistory(finBox->currentText());

    QFile f(finBox->currentText());

    if (!f.open(IO_ReadOnly)) {
        KMessageBox::error ( this, "Cannot open'"+finBox->currentText()+"'","ERROR" );
        return;
    }

    currentFileLbl->setText(finBox->currentText());

    int k; // where to load - 1
    if (appendFileBox->isChecked()) {
        k=comListBox->numRows()-1;
    } else if (insertFileBox->isChecked()) {
        k=comListBox->currentRow()-1;
    } else {
        if (comListBox->numRows()>0) {
            QMemArray<int> ir(comListBox->numRows());
            for (int i=0;i<comListBox->numRows();i++) ir[i]=i;
            comListBox->removeRows(ir);
        }
        k=-1;
        numcom=0;
        maxcomlen=0;
    }

    QTextStream t( &f );

    QString ic;
    if (eucBut->isChecked()) {
        ic="euc-JP";
    } else if (utfBut->isChecked()) {
        ic="UTF-8";
    } else if (sjisBut->isChecked()) {
        ic="Shift-JIS";
    }
    QTextCodec *codec = QTextCodec::codecForName(ic);
    if (codec==NULL) exit(1); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    t.setCodec(codec);

    QString c;
    while (!t.atEnd()) {
        t.skipWhiteSpace();
        c=t.readLine().stripWhiteSpace().simplifyWhiteSpace();
        if (c.isEmpty()) continue;
        k++;
        comListBox->insertRows(k);
        if (currentRowHeight!=0) comListBox->setRowHeight(k,currentRowHeight);
        procLine(c,k);
    }
    printLbls();
    f.close();
    runList.resize(comListBox->numRows());
    int const fpw=13; // <<<<<<<<<<<<<<<<<<<<<<<<<<<
    comListBox->setColumnWidth(1,maxcomlen*fpw);
    if (numcom>0
            &&(!ipBox->currentText().isEmpty())
            &&isValidPort()) {
        sendAllBut->setEnabled(true);
        sendSomeBut->setEnabled(true);
        sendHereBut->setEnabled(true);
    }
}

void okRunCls::updateButsSlot() {
    bool b0=(!ipBox->currentText().isEmpty());
    bool b1=b0&&isValidPort();
    pingBut->setEnabled(b0);
    sendBut->setEnabled(
        (!comBox->currentText().isEmpty())&&b1
    );
    bool b2=(numcom>0)&&b1;
    sendAllBut->setEnabled(b2);
    sendSomeBut->setEnabled(b2);
    sendHereBut->setEnabled(b2);
}

void okRunCls::cleMessSlot() {
    messBox->clear();
}

void okRunCls::finSlot() {
    if (QFile::exists(finBox->currentText())) {
        readBut->setEnabled(true);
        finBox->lineEdit()->setPaletteForegroundColor("blue");
    } else {
        readBut->setEnabled(false);
        finBox->lineEdit()->setPaletteForegroundColor("red");
    }
}

void okRunCls::sendACommand() {
    if (sp1->isRunning()) return;//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    sp1->clearArguments();
    sp1->setArguments(QStringList::split(" ",SCRPATH+SENDC));
    sp1->addArgument(ipBox->currentText());
    sp1->addArgument(portBox->currentText());
    sp1->addArgument(QString::number(stepNumBox->value()));
    sp1->addArgument(oneCommand);
    sp1->start();
}
void okRunCls::slotReadStdout1() {
    messBox->setColor("black");
    while ( sp1->canReadLineStdout() ) {
        QString line ( sp1->readLineStdout() );
        messBox->append ( line );
    }
}
void okRunCls::slotReadStderr1() {
    messBox->setColor("red");
    while ( sp1->canReadLineStderr() ) {
        QString line ( sp1->readLineStderr() );
        messBox->append ( line );
    }
}
void okRunCls::sendDone1() {
    repeatCount--;
    if (repeatCount==0) {
        loopt->stop();
    } else if (!fixedStepNumBox->isChecked()) {
        stepNumBox->stepUp();
    }
    if (!loopt->isActive()) sendBut->setOn(false);
}

void okRunCls::sendCommands() {
    int k=-1;
    while (currentRow<comListBox->numRows()) {
        if (runList[currentRow]!=0) {
            k=currentRow;
            break;
        }
        currentRow++;
    }
    if (k==-1) {
        printmsg("done.");
        setEnabledSendButs(false,true);
        return; // finished
    }
    currentStepNum++;
    comListBox->setPixmap(k,0,*fkpic);
    comListBox->setText(k,0,"running");
    comListBox->setCurrentCell(k,0);
    comListBox->selectRow(k);

    sp->clearArguments();
    sp->addArgument(SCRPATH+SENDC);
    sp->addArgument(ipBox->currentText());
    sp->addArgument(portBox->currentText());
    sp->addArgument(QString::number(currentStepNum));;
    sp->addArgument(comListBox->text(k,1));
    sp->start();
}

void okRunCls::slotReadStdouts() {
    messBox->setColor("black");
    while ( sp->canReadLineStdout() ) {
        QString line ( sp->readLineStdout() );
        messBox->append ( line );
        rep="";
        if (line.startsWith("RECV:")) {
            rep=line.section("'",1,1).remove(0,2);
        }
    }
}
void okRunCls::slotReadStderrs() {
    messBox->setColor("red");
    while ( sp->canReadLineStderr() ) {
        QString line ( sp->readLineStderr() );
        messBox->append ( line );
    }
}
void okRunCls::sendDone() {
    comListBox->clearSelection();//<<<<<<<<<<<<<<<<<<<<<<<<
    bool failed=true;
    if (sp->exitStatus()==0) {
        comListBox->setText(currentRow,0,rep);
        if (rep.contains("OK")) {
            comListBox->setPixmap(currentRow,0,*okpic);
            failed=false;
        } else {
            comListBox->setPixmap(currentRow,0,*ngpic);
        }
    } else {
        comListBox->setText(currentRow,0,"Failure");
        comListBox->setPixmap(currentRow,0,*erpic);
    }

    if (killed) {
        setEnabledSendButs(false,true);
        return;
    } else if (failed) {
        if (stopOnErrorBut->isChecked()) {
            if ( KMessageBox::No==KMessageBox::questionYesNo (
                        this,
                        tr ( "Command Failed!\nContinue?" ),
                        tr ( "Question" ),tr ( "Yes" ),tr ( "No" ) ) ) {
                printmsg("Execusion stoped by a error","red");
                setEnabledSendButs(false,true);
                return;
            }
        }
    }
    currentRow++;
    sendCommands();
}

void okRunCls::killSendSlot() {
    killed=true;
    sp->tryTerminate();
    QTimer::singleShot ( 1000,sp,SLOT ( kill() ) );
}
void okRunCls::killSend1Slot() {
    killed1=true;
    loopt->stop();
    sp1->tryTerminate();
    QTimer::singleShot ( 1000,sp1,SLOT ( kill() ) );
}

bool okRunCls::isValidPort() {
    bool ok=true;
    portBox->currentText().toUInt(&ok,10);
    return ok;
}

void okRunCls::setEnabledSendButs(bool on,bool enabled) {
    bool ok=(!ipBox->currentText().isEmpty())&&isValidPort();
    sendHereBut->setOn(on);
    sendSomeBut->setOn(on);
    sendAllBut->setOn(on);
    sendAllBut->setEnabled(enabled&&ok);
    sendSomeBut->setEnabled(enabled&&ok);
    sendHereBut->setEnabled(enabled&&ok);
}

int okRunCls::check_scr ( QString s ) {
    QString ss=s;
    if ( QFile::exists ( ss ) ) {
        struct stat sb;
        stat ( s.latin1(), &sb );
        if ( S_ISREG ( sb.st_mode ) && ( sb.st_mode & S_IXUSR ) ) {
            return 0;
        } else {
            ss.prepend ( "Permission denied: " );
        }
    } else {
        ss.prepend ( "No such script/binary file: " );
    }
    {
        KMessageBox::error ( this, ss, "ERROR" );
        printmsg ( ss,"red" );
    }
    return 1;
}

void okRunCls::printmsg(QString s, QString c) {
    messBox->setColor ( c );
    messBox->append ( s );
    messBox->setColor ( "black" );
}

void okRunCls::sendHereSlot() {
    if (sendHereBut->isOn()) {
        addHistRemoteHost();
        if (check_scr(SCRPATH+SENDC)!=0) {
            sendHereBut->setOn(false);
            return;
        }
        sendAllBut->setEnabled(false);
        sendSomeBut->setEnabled(false);
        currentRow=0;
        runList.resize(comListBox->numRows());
        runList.fill(0);
        for (int ir=comListBox->currentRow();ir<comListBox->numRows();ir++) {
            if (!comListBox->text(ir,0).isEmpty()) runList[ir]=1;
        }
        killed=false;
        currentStepNum=0;
        sendCommands();
    } else {
        killSendSlot();
    }
}

void okRunCls::sendSelectedSlot() {
    if (sendSomeBut->isOn()) {
        addHistRemoteHost();
        if (check_scr(SCRPATH+SENDC)!=0) {
            sendSomeBut->setOn(false);
            return;
        }
        sendAllBut->setEnabled(false);
        sendHereBut->setEnabled(false);
        currentRow=0;
        runList.resize(comListBox->numRows());
        runList.fill(0);
        for (int ir=0;ir<comListBox->numRows();ir++) {
            if (comListBox->isRowSelected(ir)&&(!comListBox->text(ir,0).isEmpty())) runList[ir]=1;
        }
        killed=false;
        currentStepNum=0;
        sendCommands();
    } else {
        killSendSlot();
    }
}

void okRunCls::sendAllSlot() {
    if (sendAllBut->isOn()) {
        addHistRemoteHost();
        if (check_scr(SCRPATH+SENDC)!=0) {
            sendAllBut->setOn(false);
            return;
        }
        sendSomeBut->setEnabled(false);
        sendHereBut->setEnabled(false);
        currentRow=0;
        runList.resize(comListBox->numRows());
        runList.fill(0);
        for (int ir=0;ir<comListBox->numRows();ir++) {
            if (!comListBox->text(ir,0).isEmpty()) runList[ir]=1;
        }
        killed=false;
        currentStepNum=0;
        sendCommands();
    } else {
        killSendSlot();
    }
}

void okRunCls::editComListSlot(int r, int c) {
    bool st=(!comListBox->text(r,0).isEmpty());
    procLine(comListBox->text(r,1),r,false);
    if (st&&comListBox->text(r,0).isEmpty()) {
        numcom--;
        printLbls();
    }
}

void okRunCls::selectClearSlot() {
    comListBox->clearSelection();
}

void okRunCls::selectAllSlot() {
    for (int ir=0;ir<comListBox->numRows();ir++) {
        comListBox->selectRow(ir);
    }
}

void okRunCls::uncommentSlot() {
    comListBox->blockSignals(true);
    for (int ir=0;ir<comListBox->numRows();ir++) {
        if (comListBox->isRowSelected(ir)
                &&comListBox->text(ir,0).isEmpty()
                &&(!comListBox->text(ir,1).isEmpty())) {
            comListBox->setText(ir,2,"");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            procLine(
                comListBox->text(ir,1).right(comListBox->text(ir,1).length()-1),
                ir);
        }
    }
    comListBox->blockSignals(false);
}

void okRunCls::commentSlot() {
    for (int ir=0;ir<comListBox->numRows();ir++) {
        if (comListBox->isRowSelected(ir)
                &&(!comListBox->text(ir,0).isEmpty())
                &&(!comListBox->text(ir,1).isEmpty())) {
            procLine("#"+comListBox->text(ir,1),ir);
            numcom--;
            printLbls();
        }
    }
}

void okRunCls::removeSlot() {
    int cc=comListBox->currentColumn();
    int cr=comListBox->currentRow();
    int nd=0;
    QMemArray<bool> del(comListBox->numRows());
    for (int ir=0;ir<comListBox->numRows();ir++) {
        del[ir]=comListBox->isRowSelected(ir);
    }
    for (int ir=comListBox->numRows()-1;ir>=0;ir--) {
        if (del[ir]) {
            if (!comListBox->text(ir,0).isEmpty()) numcom--;
            nd++;
            comListBox->removeRow(ir);
            printLbls();
        }
    }
    if (nd==0) {
        if (!comListBox->text(cr,0).isEmpty()) numcom--;
        comListBox->removeRow(cr);
        printLbls();
    }
    comListBox->setCurrentCell(cr,cc);
}

void okRunCls::addSlot() {
    int cr=comListBox->currentRow();
    int cc=comListBox->currentColumn();
    comListBox->insertRows(cr);
    comListBox->setCurrentCell(cr,cc);
    printLbls();
}

void okRunCls::insertFileSlot() {
    if (insertFileBox->isChecked()) {
        appendFileBox->setChecked(false);
    }
}
void okRunCls::appendFileSlot() {
    if (appendFileBox->isChecked()) {
        insertFileBox->setChecked(false);
    }
}

void okRunCls::enableRepeatSlot() {
    repeatGrp->setEnabled(repeatBox->isChecked());
}

void okRunCls::addHistRemoteHost() {
    ipBox->addToHistory(ipBox->currentText());
    if (isValidPort()) portBox->addToHistory(portBox->currentText());
}

void okRunCls::sendOneSlot() {
    if (sendBut->isOn()) {
        addHistRemoteHost();
        if (check_scr(SCRPATH+SENDC)!=0) {
            sendBut->setOn(false);
            return;
        }
        oneCommand=comBox->currentText();
        comBox->addToHistory(oneCommand);
        killed1=false;

        if (repeatBox->isChecked()) {
            repeatCount=countBox->value();
            repeatInterval=intervalBox->value()*1000;
            loopt->start(repeatInterval);
        } else {
            repeatCount=1;
            repeatInterval=0;
            loopt->start(0,true);
        }
    } else {
        killSend1Slot();
    }
}

void okRunCls::pingSlot() {
    if (!pingBut->isOn()) {
        pp->tryTerminate();
        QTimer::singleShot ( 1000,pp,SLOT ( kill() ) );
        return;
    }
    pp->clearArguments();
    pp->setArguments(QStringList::split(" ",PING));
    pp->addArgument(ipBox->currentText());
    addHistRemoteHost();
    pp->start();
}
void okRunCls::slotReadStdoutp() {
    messBox->setColor("black");
    while ( pp->canReadLineStdout() ) {
        QString line ( pp->readLineStdout() );
        messBox->append ( line );
    }
}
void okRunCls::slotReadStderrp() {
    messBox->setColor("red");
    while ( pp->canReadLineStderr() ) {
        QString line ( pp->readLineStderr() );
        messBox->append ( line );
    }
}
void okRunCls::sendDonep() {
    pingBut->setOn(false);
}

void okRunCls::keyPressEvent(QKeyEvent *e) {
    switch (e->key()) {
    case Qt::Key_Q:
    case Qt::Key_Escape:
        close();
        break;
    case Qt::Key_Plus:
        if (messBox->hasFocus()) changeFontSizeMess(1);
        if (comListBox->hasFocus()) changeFontSizeCom(1);
        break;
    case Qt::Key_Minus:
        if (messBox->hasFocus()) changeFontSizeMess(-1);
        if (comListBox->hasFocus()) changeFontSizeCom(-1);
        break;
    }
}

void okRunCls::changeFontSizeMess(int d) {
    QFont f=messBox->font();
    int ps=f.pointSize()+d;
    f.setPointSize(ps);
    messBox->setFont(f);
}

void okRunCls::changeFontSizeCom(int d) {
    QFont f=comListBox->font();
    int ps=f.pointSize()+d;
    int pps=ps*1.5; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    f.setPointSize(ps);
    comListBox->setFont(f);
    for (int ir=0;ir<comListBox->numRows();ir++) {
        comListBox->setRowHeight(ir,pps);
    }
    currentRowHeight=pps;
    comListBox->setTopMargin(ps*1.5);
    comListBox->setLeftMargin(ps*3.8);
}

void okRunCls::shrMessSlot() {
    changeFontSizeMess(-1);
}

void okRunCls::magMessSlot() {
    changeFontSizeMess(1);
}

void okRunCls::shrComSlot() {
    changeFontSizeCom(-1);
}

void okRunCls::magComSlot() {
    changeFontSizeCom(1);
}

void okRunCls::cleStaSlot() {
    for (int ir=0;ir<comListBox->numRows();ir++) {
        bool b=(!comListBox->text(ir,0).isEmpty());
        comListBox->clearCell(ir,0);
        if (b) comListBox->setText(ir,0,"ready");
    }
}

void okRunCls::printLbls() {
    numComLbl->setText(QString::number(numcom)+" com");
    numLineLbl->setText(QString::number(comListBox->numRows())+" line");
}

void okRunCls::saveSlot() {
    QString fout = KFileDialog::getSaveFileName ( "",
                   "*.txt|text file (*.txt)\n*.*|All (*.*)",
                   this,
                   tr ( "Save File As" ) );
    if (fout.isEmpty()) return;
    QFile f(fout);
    if (!f.open(IO_WriteOnly)) {
        KMessageBox::error ( this, "Cannot write'"+fout+"'","ERROR" );
        return;
    }
    QTextStream t( &f );
    QString ic;
    QString lf="\n";
    if (eucBut->isChecked()) {
        ic="euc-JP";
    } else if (utfBut->isChecked()) {
        ic="UTF-8";
    } else if (sjisBut->isChecked()) {
        ic="Shift-JIS";
        lf="\r\n";
    }
    QTextCodec *codec = QTextCodec::codecForName(ic);
    if (codec==NULL) exit(1); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    t.setCodec(codec);
    for (int ir=0;ir<comListBox->numRows();ir++) {
        t << comListBox->text(ir,1);
        if (!comListBox->text(ir,2).isEmpty()) {
            t << " ";
            t << comListBox->text(ir,2);
        }
        t << lf;
    }
    f.close();
    printmsg("File "+fout+" written.");
}

#include "okruncls.moc"
